#include "ActivationNeuron.h"
#include "BackpropagationSynapse.h"
#include "../Helper.h"

using namespace NeuralPlusPlus::Core;
using namespace NeuralPlusPlus::Core::Backpropagation;

NeuralPlusPlus::Core::Backpropagation::ActivationNeuron::ActivationNeuron( ActivationLayer *parent )
	{
	Helper::ValidateNotNull(parent, "parent");
	this->Input = 0.0;
	this->Output = 0.0;
	this->Error = 0.0;
	this->Bias = 0.0;
	this->Parent = parent;
	}

void NeuralPlusPlus::Core::Backpropagation::ActivationNeuron::Run()
	{
	int sourceSynapsesSize = SourceSynapses.size();
	if (sourceSynapsesSize > 0)
		{
		Input = 0.0;
		for(int i=0;i<sourceSynapsesSize;i++)
			{
			((BackpropagationSynapse*)SourceSynapses[i])->Propagate();
			}
		}
	Output = ((ActivationLayer*)Parent)->Activate(Bias + Input, Output);
	}

void NeuralPlusPlus::Core::Backpropagation::ActivationNeuron::EvaluateError()
	{
	int targetSynapseSize = TargetSynapses.size();
	if (targetSynapseSize > 0)
		{
		Error = 0.0;
		for(int i=0;i<targetSynapseSize;i++)
			{
			((BackpropagationSynapse*)TargetSynapses[i])->Backpropagate();
			}
		}
	Error *= ((ActivationLayer*)Parent)->Derivative(Input, Output);
	}

void NeuralPlusPlus::Core::Backpropagation::ActivationNeuron::Learn( double learningRate )
	{
	if (!((ActivationLayer*)Parent)->UseFixedBiasValues)
		{
		Bias += learningRate * Error;
		}
	int sourceSynapsesSize = SourceSynapses.size();
	for(int i=0;i<sourceSynapsesSize;i++)
		{
		((BackpropagationSynapse*)SourceSynapses[i])->OptimizeWeight(learningRate);
		}
	}